#!/usr/bin/python
import sys
import os
import re

# unpack packages listed in file sys.argv[1], 
# unpacked folder name is basename of filename
# apply patch listed in file sys.argv[2]

if len(sys.argv)<3: raise Exception('Requires two arguments.')
pkglist=open(sys.argv[1],'r')
patchlist=open(sys.argv[2],'r')

os.chdir(os.path.dirname(os.path.abspath(sys.argv[0]))) # chdir to the directory where `unpack' stays

if not os.path.exists('tmp'): os.mkdir('tmp')

dirs=[] # directories to apply patch

# unpack
os.chdir('tmp')

for pkg in pkglist:
	pkg=pkg.strip()

	if not os.path.exists(pkg): raise Exception('Pkg not exists.', pkg)

	# get filename(*.tar.gz *.tar.bz2) from file_path(/source/*)
	filename=os.path.basename(pkg)

	# get basename from filename
	if re.search(r'\.tar\.gz$', filename):
		basename=re.search(r'(.+)\.tar\.gz$',filename).group(1)
	elif re.search(r'\.tar\.bz2$', filename):
		basename=re.search(r'(.+)\.tar\.bz2$',filename).group(1)
	else:
		raise Exception('Unsupported package format. ',pkg)

	cmd='tar xf %s'%pkg

	# if not exist ../basename, then unpack
	if os.path.exists('../'+basename)==False:
		print cmd
		if os.system(cmd): raise Exception('Cannot unpack',pkg,cmd)
		if len(os.listdir('.'))>1: raise Exception('More than one dir unpacked.')
		if os.system('mv %s ../%s'%(os.listdir('.')[0],basename)):
			raise Exception('Cannot mv','mv %s ../%s'%(os.listdir('.')[0],basename))
	dirs.append(basename)
if len(dirs)==0: raise Exception('No pkg provided.')

os.chdir('..')
os.rmdir('tmp')

def match(L,s): # return the element match `s' in `L'
	ret=None
	for l in L:
		if re.search(s,l):
			if ret: raise Exception('more than one match.', L, s)
			ret=l
	if ret==None: raise Exception('no element matches.', L, s)
	return ret

# patch
order=[
('gmp','branch_update'), 
('mpfr','branch_update'),
('binutils','posix'),
('binutils','branch_update'),
# ('gcc','posix'), # no longer exists in gcc 4.4.1
('gcc','branch_update'),
('gcc','pure64'),
('gcc','cross_compile_ecj'),
('glibc-[^p]','libgcc_eh'), # choose glibc, not choose glibc-ports
('glibc-[^p]','localedef_segfault'),
# ('glibc-[^p]','cross_hacks'),
# ('glibc-[^p]','arm_setjmp_fix'), # FIXME: Cannot apply
# ('glibc-[^p]','nptl_lowlevellock'), # FIXME: Cannot apply
]

patch=[] # contains basename of patches.
for p in patchlist:
	p=p.strip()
	if len(p)>0: patch.append(os.path.basename(p.strip()))
	if re.search('\.patch$',p)==None: raise Exception(patchlist.name+'format error.')
	if not os.path.exists(p): raise Exception('Patch not exists.', p)
if len(patch)==0: raise Exception('No patch provided in '+patchlist.name)

for (s1,s2) in order:
	s1=match(dirs, s1) # dir name
	s2=match(patch, '%s.+%s'%(s1,s2) ) # patch basename
	patchpath='/source/'+s2 # patch file path
	os.chdir(s1)
	if not os.path.exists(s2):
		patchcmd='patch --silent -Np1 -i '+patchpath
		print patchcmd
		if os.system(patchcmd): raise Exception('Cannot patch', patchcmd)
		if os.system('cp %s .'%patchpath): raise Exception('Cannot cp. Please remove the whole dir.', 'cp %s .'%patchpath)
	os.chdir('..')
